package my.study.c.consul.consumer.app.util;

import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager;
import org.apache.hc.core5.reactor.IOReactorConfig;
import org.apache.hc.core5.util.Timeout;

public class MyAsyncHttpClientUtil {

    /*
     * defaultMaxPerRoute说明
     * 每一个 local IP => remoteIP : port 为一个route，
     * 在向http服务器单一（ip,port）对发送请求时，这个参数控制了可以建立的tcp连接上限, 向设备后台发送的连接限制应该和连接池大小相差无几
     */
    public static final int MAX_CONNECTIONS_PER_ROUTE = 100; //路由连接大小
    public static final int MAX_TOTAL_CONNECTIONS = 120;    //连接池大小
    public static final long SO_TIMEOUT = 5000; //超时数

    private MyAsyncHttpClientUtil() {
    }

    public static CloseableHttpAsyncClient getInstance() {
        return CloseableHttpAsyncClientSingleton.INSTANCE.getInstance();
    }

    /**
     * 枚举类型是线程安全的，并且只会装载一次
     */
    private enum CloseableHttpAsyncClientSingleton {
        INSTANCE;

        private final CloseableHttpAsyncClient httpAsyncClient;

        CloseableHttpAsyncClientSingleton() {
            IOReactorConfig ioReactorConfig = IOReactorConfig.custom()
                    .setSoTimeout(Timeout.ofMilliseconds(SO_TIMEOUT))
                    .build();

            PoolingAsyncClientConnectionManager cm = new PoolingAsyncClientConnectionManager();
            cm.setMaxTotal(MAX_TOTAL_CONNECTIONS); //线程数
            cm.setDefaultMaxPerRoute(MAX_CONNECTIONS_PER_ROUTE);//每ip:port 连接数

            httpAsyncClient = HttpAsyncClients.custom()
                    .setConnectionManager(cm)
                    .setIOReactorConfig(ioReactorConfig)
                    .build();
        }

        private CloseableHttpAsyncClient getInstance() {
            return httpAsyncClient;
        }
    }
}
